package com.bingo.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bingo.common.R;
import com.bingo.dao.PutMapper;
import com.bingo.entity.*;
import com.bingo.entity.dto.NewSeedLings;
import com.bingo.entity.dto.everyDayForm.EveryDayPut;
import com.bingo.entity.dto.intermediary.SitePut;
import com.bingo.entity.dto.resp.PutRecord;
import com.bingo.entity.dto.resp.ReportBasic;
import com.bingo.entity.dto.resp.RespSitePut;
import com.bingo.entity.dto.todayForm.TodayPut;
import com.bingo.service.*;
import com.bingo.until.HostHolder;
import com.bingo.until.IsToday;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

@Service
public class PutServiceImpl extends ServiceImpl<PutMapper, Put> implements PutService {

    private HisPoolServiceImpl poolService;
    @Autowired
    public void setPoolService(HisPoolServiceImpl poolService) {
        this.poolService = poolService;
    }

    private HostHolder hostHolder;
    @Autowired
    public void setHostHolder(HostHolder hostHolder) {
        this.hostHolder = hostHolder;
    }

    private CurPoolService curPoolService;
    @Autowired
    public void setPrePoolService(CurPoolService curPoolService) {
        this.curPoolService = curPoolService;
    }

    private UserService userService;
    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    private SiteService siteService;
    @Autowired
    public void setSiteService(SiteService siteService) {
        this.siteService = siteService;
    }

    private BaseDataService baseDataService;
    @Autowired
    public void setBaseDataService(BaseDataService baseDataService) {
        this.baseDataService = baseDataService;
    }

    //汇总投塘记录
    @Override
    public NewSeedLings getNewSeedLings(String poolNo, Date startDate, Date endDate) {
        NewSeedLings newSeedLings = new NewSeedLings();
        newSeedLings.setAmount(0);
        newSeedLings.setWeight(0.0);
        QueryWrapper<Put> wrapper = new QueryWrapper<>();
        wrapper.eq("pool_no", poolNo);
        wrapper.between("date", startDate, endDate);
        List<Put> list = this.list(wrapper);
        for (Put put : list) {
            newSeedLings.setAmount(newSeedLings.getAmount() + put.getQuantity());
            newSeedLings.setWeight(newSeedLings.getWeight() + put.getWeight());
        }
        if (newSeedLings.getWeight() == 0.0 || newSeedLings.getAmount() == 0) {
            newSeedLings.setSize(0.0);
        }else {
            newSeedLings.setSize(newSeedLings.getAmount() / newSeedLings.getWeight());
        }
        return newSeedLings;
    }

    //新增投苗记录
    @Override
    public R addPut(String poolNo, Integer quantity, Double weight, Date date, String userId, Integer isUpdate) {

        //当前请求用户的id
        userId = hostHolder.getUser().getUserId();

        CurPool curPool = curPoolService.getCurPoolByNo(poolNo);
        if (curPool == null) {
            return R.error("当前不存在该塘！");
        }

        if ((isUpdate==null||isUpdate==0)&& curPool.getType()!=0){
            return R.error("投苗日期未存在该塘或当前不是空塘，不可投苗，如需修改之前投苗记录请将参数isUpdate修改为1！");
        }

        HisPool hisPool = poolService.getPoolByNoAndDate(poolNo, date);
        if (!(isUpdate==null||isUpdate==0)&&(hisPool == null && isUpdate==1)&&!IsToday.isToday(date)){
            return R.error("发生日期还不存在该塘！");
        }

        if (hisPool !=null&&(isUpdate==null||isUpdate==0)&& hisPool.getType()!=0){
            return R.error("发生日期："+date+"该塘不是空塘，不可投苗，如需修改之前投苗记录请将参数isUpdate修改为1！");
        }


        //查询历史记录
        QueryWrapper<Put> wrapper = new QueryWrapper<>();
        wrapper.eq("pool_no", poolNo);
        wrapper.eq("date", date);
        Put old = this.getOne(wrapper);

        if (old==null){

            //组装完整的投塘记录并存入数据库
            Put put = new Put();
            put.setPoolNo(poolNo);
            put.setQuantity(quantity);
            put.setWeight(weight);
            put.setDate(date);
            put.setUserId(userId);
            put.setReportDate(new Date(System.currentTimeMillis()));
            this.save(put);
            //更新塘口信息
            curPool.setQuantity(curPool.getQuantity() + quantity);
            curPool.setWeight(curPool.getWeight() + weight);
            curPool.setType(1);
            curPoolService.updateById(curPool);

            //如果不是当天
            if (!IsToday.isToday(date)) {
                QueryWrapper<HisPool> wrapper1 = new QueryWrapper<>();
                wrapper1.eq("pool_no", poolNo);
                wrapper1.between("date", date, new Date(System.currentTimeMillis()));
                List<HisPool> list = poolService.list(wrapper1);
                for (HisPool p : list) {
                    p.setQuantity(p.getQuantity() + quantity);
                    p.setWeight(p.getWeight() + weight);
                    curPool.setType(1);
                    poolService.updateById(p);
                }
            }

            boolean changeOld = this.isChangeOld(date);

            R<String> r = R.success("新增投塘记录成功,是否进行新老变更："+changeOld);
            r.setStatusText("新增投塘记录成功");
            return r;
        }
        else {
            //计算差值
            int quantity1 = quantity - old.getQuantity();
            double weight1 = weight - old.getWeight();
            //更新投塘记录
            old.setQuantity(quantity);
            old.setWeight(weight);
            old.setReportDate(new Date(System.currentTimeMillis()));
            this.updateById(old);
            //更新塘口信息
            curPool.setQuantity(curPool.getQuantity() + quantity1);
            curPool.setWeight(curPool.getWeight() + weight1);
            curPoolService.updateById(curPool);
            //如果不是当天
            if (!IsToday.isToday(date)) {
                QueryWrapper<HisPool> wrapper2 = new QueryWrapper<>();
                wrapper2.eq("pool_no", poolNo);
                wrapper2.between("date", date, new Date(System.currentTimeMillis()));
                List<HisPool> list = poolService.list(wrapper2);
                for (HisPool p : list) {
                    p.setQuantity(p.getQuantity() + quantity1);
                    p.setWeight(p.getWeight() + weight1);
                    poolService.updateById(p);
                }
            }
            R<String> r = R.success("修改投塘记录成功！");
            return r;

        }
    }

    @Override
    public List<EveryDayPut> selectEveryDayPut(List<String> poolNos, Date startDate, Date endDate) {

        if (poolNos == null || poolNos.size() == 0) {
            poolNos = curPoolService.getPoolNos();
        }

        LinkedList<EveryDayPut> list = new LinkedList<>();

        for (String poolNo : poolNos) {
            CurPool pool = curPoolService.getCurPoolByNo(poolNo);
            //初始化
            EveryDayPut dayPut = new EveryDayPut();
            dayPut.setPoolNo(poolNo);
            dayPut.setTotalQuantity(0);
            dayPut.setTotalWeight(0.0);
            dayPut.setArea(pool.getArea());
            dayPut.setKey(poolNo);
            //LinkedList<TodayPut> todayPuts = new LinkedList<>();
            HashMap<String, TodayPut> todayPuts = new HashMap<>();


            QueryWrapper<Put> wrapper = new QueryWrapper<>();
            wrapper.eq("pool_no", poolNo);
            wrapper.between("date", startDate, endDate);
            List<Put> puts = this.list(wrapper);
            for (Put put : puts) {
                TodayPut todayPut = new TodayPut();
                todayPut.setPoolNo(put.getPoolNo());
                todayPut.setQuantity(put.getQuantity());
                todayPut.setWeight(put.getWeight());
                todayPut.setDate(put.getDate());
                dayPut.setTotalQuantity(dayPut.getTotalQuantity() + put.getQuantity());
                dayPut.setTotalWeight(dayPut.getTotalWeight() + put.getWeight());
                //todayPuts.add(todayPut);
                if(todayPuts.containsKey(put.getDate().toString())){
                    TodayPut todayPut1 = todayPuts.get(put.getDate().toString());
                    todayPut1.setQuantity(todayPut1.getQuantity()+put.getQuantity());
                    todayPut1.setWeight(todayPut1.getWeight()+put.getWeight());
                    todayPuts.put(put.getDate().toString(),todayPut1);
                }else {
                    todayPuts.put(put.getDate().toString(),todayPut);
                }
            }
            //dayPut.setDataList(todayPuts);
            dayPut.setDataMap(todayPuts);
            list.add(dayPut);
        }


        return list;
    }

    @Override
    public List<PutRecord> selectPutRecord(List<String> poolNos, Date startDate, Date endDate,String userId) {
        if (poolNos == null || poolNos.size() == 0){
            poolNos = curPoolService.getPoolNos();
        }

        QueryWrapper<Put> wrapper = new QueryWrapper<>();
        wrapper.in("pool_no", poolNos);
        wrapper.between("date", startDate, endDate);
        if (userId != null && !userId.equals("")){
            wrapper.eq("user_id", userId);
        }
        List<Put> list = this.list(wrapper);

        LinkedList<PutRecord> putRecords = new LinkedList<>();
        HashMap<String, String> allUser = userService.getAllUser();

        for (Put put : list) {
            PutRecord putRecord = new PutRecord();
            ReportBasic reportBasic = new ReportBasic();
            reportBasic.setPoolNo(put.getPoolNo());
            String s = allUser.get(put.getUserId());
            reportBasic.setReporter(s);
            reportBasic.setDate(put.getDate());
            reportBasic.setReportDate(put.getReportDate());
            putRecord.setReportBasic(reportBasic);
            putRecord.setQuantity(put.getQuantity());
            putRecord.setWeight(put.getWeight());
            putRecords.add(putRecord);
        }

        return putRecords;
    }

    @Override
    public List<RespSitePut> selectSitePut(List<String> siteNos, Date startDate, Date endDate) {
        if (siteNos == null || siteNos.size() == 0) {
            siteNos = siteService.getAllSiteNo();
        }
        LinkedList<RespSitePut> list = new LinkedList<>();

        for (String siteNo : siteNos) {
            RespSitePut respSitePut = this.initRespSitePut(siteNo);
            //初始化dataMap
            this.initDataMap(respSitePut, startDate, endDate);
            list.add(respSitePut);
            //获取该场全部塘口
            List<String> poolNos = curPoolService.getPoolsBySiteNo(siteNo);
            if (poolNos == null || poolNos.size() == 0) {
                continue;
            }
            QueryWrapper<Put> wrapper = new QueryWrapper<>();
            wrapper.in("pool_no", poolNos);
            wrapper.between("date", startDate, endDate);
            List<Put> puts = this.list(wrapper);
            /*for (Put put : puts) {
                if (sitePutHashMap.containsKey(put.getDate().toString())) {
                    SitePut sitePut = sitePutHashMap.get(put.getPoolNo());
                    sitePut.setQuantity(sitePut.getQuantity() + put.getQuantity());
                    sitePut.setWeight(sitePut.getWeight() + put.getWeight());
                    sitePutHashMap.put(put.getPoolNo(), sitePut);
                }else {
                    SitePut sitePut = new SitePut();
                    sitePut.setQuantity(put.getQuantity());
                    sitePut.setWeight(put.getWeight());
                    sitePut.setDate(put.getDate());
                    sitePutHashMap.put(put.getDate().toString(), sitePut);
                }
                respSitePut.setTotalAccount(respSitePut.getTotalAccount() + put.getQuantity());
                respSitePut.setTotalWeight(respSitePut.getTotalWeight() + put.getWeight());
            }*/

            for (Put put : puts) {
                HashMap<String, SitePut> dataMap = respSitePut.getDataMap();
                SitePut sitePut = dataMap.get(put.getDate().toString());
                sitePut.setQuantity(sitePut.getQuantity() + put.getQuantity());
                sitePut.setWeight(sitePut.getWeight() + put.getWeight());
                dataMap.put(put.getDate().toString(), sitePut);
                respSitePut.setTotalAccount(respSitePut.getTotalAccount() + put.getQuantity());
                respSitePut.setTotalWeight(respSitePut.getTotalWeight() + put.getWeight());
            }

        }
        return list;
    }


    private boolean isChangeOld(Date date){
        String s = baseDataService.selectValueByName("year");
        if (date.getYear()+1900==Integer.parseInt(s)){
            //不是当年第一次投苗，不进行新老变更
            return false;
        }
        QueryWrapper<CurPool> wrapper = new QueryWrapper<>();
        wrapper.eq("type", 1);
        List<CurPool> list = curPoolService.list(wrapper);
        for (CurPool curPool : list) {
            //有鳗鱼的改为老鳗
            if (curPool.getQuantity()!=0&&curPool.getWeight()!=0){
                curPool.setType(2);
            }
            curPoolService.updateById(curPool);
        }

        QueryWrapper<BaseData> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("name", "year");
        BaseData baseData = baseDataService.getOne(wrapper1);
        baseData.setValue(String.valueOf(date.getYear()+1900));
        baseDataService.updateById(baseData);
        return true;

    }

    private RespSitePut initRespSitePut(String siteNo){
        RespSitePut respSitePut = new RespSitePut();
        respSitePut.setSiteNo(siteNo);
        Site site = siteService.getSiteByNo(siteNo);
        respSitePut.setArea(site.getArea());
        respSitePut.setKey(siteNo);
        respSitePut.setTotalAccount(0);
        respSitePut.setTotalWeight(0.0);
        HashMap<String, SitePut> sitePutHashMap = new HashMap<>();
        respSitePut.setDataMap(sitePutHashMap);
        return respSitePut;
    }

    private void initDataMap(RespSitePut respSitePut,Date startTime,Date endTime){
        HashMap<String, SitePut> dataMap = respSitePut.getDataMap();
        Date tmpDate = new Date(startTime.getTime());
        //初始化dataMap
        while (tmpDate.getTime() <= endTime.getTime()) {
            SitePut sitePut = new SitePut();
            sitePut.setQuantity(0);
            sitePut.setWeight(0.0);
            sitePut.setDate(new Date(tmpDate.getTime()));
            dataMap.put(tmpDate.toString(), sitePut);
            tmpDate.setTime(tmpDate.getTime() + 24 * 60 * 60 * 1000);
        }
    }
}
